using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using CMS.api.Entity;
using CMS.api.Model;
using Microsoft.IdentityModel.Tokens;

namespace CMS.api.Utils
{

    // 用于生成token的帮助类
    public class TokenHelper
    {
        public static string GenerateToken(TokenParameter tokenParameter ,Users user)
        {
            // 自定义的Token密钥 (最少在16位以上) 注:不能泄露，泄露意味着所有人都可以生成你的token并且访问你的服务或者接口
            var secret = tokenParameter.Secret;

            // Encoding.UTF8.GetBytes()方法 用于把字符串转换成UTF8格式的字节。 在System.Text命名空间下。
            // SymmetricSecurityKey()构造函数 通常,该类由基础结构用来使用对称密钥转换 XML。 用于生成数字签名证书的加密密钥,参数必须是bytes类型的。 在Microsoft.IdentityModel.Tokens命名空间下。
            var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret));  // 生成数字签名需要的加密密钥

            // SigningCredentials()构造函数 用于签发数字签名证书。创建JWS Compact JSON。 在System.IdentityModel.Tokens命名空间下。
            // 参数1: 加密密钥  secretKey
            // 参数2：需要生成数字签名证书的加密算法 SecurityAlgorithms.HmacSha256
            // 参数3: 
            var credentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);    // 生成数字签名证书

            // 自定义的信息。是一个Claim类可迭代的泛型
            var claims = new[] {
                //添加自定义信息
                new Claim(ClaimTypes.Name,user.Username),
                new Claim(ClaimTypes.Role,"hcj")
            };

            // 创建安全令牌的构造函数 
            var jwtToken = new JwtSecurityToken(
                issuer: tokenParameter.Issuer,  // 发行者
                audience: "hcj", // 发行给谁
                // null,
                claims, // 自定义信息
                expires: DateTime.Now.AddMinutes(tokenParameter.AccessExpiration),  // Token有效时间
                signingCredentials: credentials  // 指定数字签名证书
            );
            
            // JwtSecurityTokenHandler()构造函数,可以验证令牌,其他特性可以去官网查看。
            // WriteToken()用于写安全令牌。将JwtSecurityToken序列化为紧凑序列化格式的 JWT。在System.IdentityModel.Tokens.Jwt命名空间下。
            var token = new JwtSecurityTokenHandler().WriteToken(jwtToken);     // 生成安全令牌。
            
            // 返回令牌
            return token;
        }


    }
}